package com.cloud.animationtestdemo.utils

import android.annotation.SuppressLint
import android.content.Context
import android.text.TextUtils
import android.util.Log
import android.view.ContextThemeWrapper
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.coroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.withContext
import java.util.Collections
import java.util.Locale

/**
 * 配置改变事件监听
 */
@SuppressLint("StaticFieldLeak")
object EasyConfigChangeManager : LifecycleEventObserver {
    private const val TAG = "ConfigChangeManager"
    private var mDisplayLanguage: String
    private val mSet = Collections.synchronizedSet(HashSet<EasyConfigChangeListener?>())
    private lateinit var mDisplayTheme: String
    private lateinit var mFirstDisplayTheme: String
    private var mLifecycle: Lifecycle? = null
    private val mutex = Mutex()
    private var isFirst = true
    private lateinit var context:Context
    init {
        mDisplayLanguage = Locale.getDefault().language

        isFirst = true
    }

    fun init(lifecycle: Lifecycle,context: Context) {
        this.context = context
        mDisplayTheme = getTheme(context)
        mFirstDisplayTheme = mDisplayTheme
        mLifecycle = lifecycle.apply {
            this.addObserver(this@EasyConfigChangeManager)
        }
    }

    fun release() {
        mLifecycle?.removeObserver(this)
    }

    fun add(configChangeListener: EasyConfigChangeListener) {
        mLifecycle?.coroutineScope?.launch(Dispatchers.Default) {
            mutex.lock()
            try {
                if (!mSet.contains(configChangeListener)) {
                    mSet.add(configChangeListener)
                }
            } finally {
                mutex.unlock()
            }

        }
    }

    fun remove(configChangeListener: EasyConfigChangeListener) {
        mLifecycle?.coroutineScope?.launch(Dispatchers.Default) {
            mutex.lock()
            try {
                if (mSet.contains(configChangeListener)) {
                    mSet.remove(configChangeListener)
                }
            } finally {
                mutex.unlock()
            }

        }
    }


     fun getTheme(context:Context): String {
         val theme = (context as? ContextThemeWrapper)?.getTheme()
        return theme.toString()
    }


    fun checkLanguage() {
        mLifecycle?.coroutineScope?.launch(Dispatchers.Default) {
            if (mSet.isEmpty()) {
                Log.d(TAG,"ConfigChangeManager checkLanguage mSet is empty")
                return@launch
            }
            val language = Locale.getDefault().language
            Log.d(TAG,"mDisplayLanguage=$mDisplayLanguage language=$language")
            if (language != mDisplayLanguage) {
                Log.d(TAG,"changeLanguage itemSize=${mSet.size}")
                mDisplayLanguage = language
                mutex.lock()
                try {
                    mSet.forEach { l ->
                        withContext(Dispatchers.Main) {
                            l?.applyLanguage()
                        }
                    }
                } finally {
                    mutex.unlock()
                }

            }

        }
    }

    /**
     * 应用首次打开 校验主题
     */
    fun firstCheckTheme() : Boolean {
        val theme = getTheme(context)
        Log.d(TAG,"firstCheckTheme mFirstDisplayTheme=$mFirstDisplayTheme theme=$theme isFirst=$isFirst")
        return TextUtils.equals(mFirstDisplayTheme, theme) && isFirst
    }

    fun checkTheme() {
        mLifecycle?.coroutineScope?.launch(Dispatchers.Default) {
            if (mSet.isEmpty()) {
                Log.d(TAG,"ConfigChangeManager checkTheme mSet is empty")
                return@launch
            }
            val theme = getTheme(context)
            Log.d(TAG,"mDisplayTheme=$mDisplayTheme theme=$theme")
            //先注释掉，后面看看是否有用
//            SkinViewManager.applyTheme()
            if (theme != mDisplayTheme) {
                Log.d(TAG,"applyTheme itemSize=${mSet.size}")
                mDisplayTheme = theme
                mutex.lock()
                try {
                    mSet.forEach { t ->
                        withContext(Dispatchers.Main) {
                            t?.applyTheme()
                        }
                    }
                } finally {
                    isFirst = false
                    mutex.unlock()
                }

            }
        }
    }

    fun recoverSetting() {
        mLifecycle?.coroutineScope?.launch(Dispatchers.Default) {
            if (mSet.isEmpty()) {
                Log.d(TAG,"ConfigChangeManager recoverSetting mSet is empty")
                return@launch
            }
            Log.d(TAG,"recoverSetting")
            mutex.lock()
            try {
                mSet.forEach { t ->
                    withContext(Dispatchers.Main) {
                        t?.recoverySetting()
                    }
                }
            } finally {
                mutex.unlock()
            }
        }

    }

    fun viewEnable(isEnable: Boolean) {

        mLifecycle?.coroutineScope?.launch(Dispatchers.Default) {
            if (mSet.isEmpty()) {
                Log.d(TAG,"ConfigChangeManager recoverSetting mSet is empty")
                return@launch
            }
            Log.d(TAG,"viewEnable=$isEnable")
            mutex.lock()
            try {
                mSet.forEach {
                    withContext(Dispatchers.Main) {
                        Log.d(TAG,"$it viewEnable =$isEnable")
                        it?.viewEnable(isEnable)
                    }
                }
            } finally {
                mutex.unlock()
            }

        }

    }

    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        when (event) {
            Lifecycle.Event.ON_CREATE -> {
                //TODO
            }

            Lifecycle.Event.ON_DESTROY -> {
                //取消注册
                mSet.clear()
            }

            else -> {
                //TODO
            }
        }
    }

}